package cn.turboinfo.dongying.api.domain.util;

import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.temporal.ChronoField.*;

public class DateTimeFormatHelper {

    public static final DateTimeFormatter defaultParseLocalDateTimeFormatter = new DateTimeFormatterBuilder()
            .appendPattern(DateTimeFormatHelper.DATE_TIME)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
            .toFormatter();

    public static final DateTimeFormatter defaultParseLocalDateFormatter = new DateTimeFormatterBuilder()
            .appendPattern(DateTimeFormatHelper.DATE)
            .toFormatter();

    public static final DateTimeFormatter wechatDataTime = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .parseLenient()
            .appendOffsetId()
            .parseStrict()
            .toFormatter();

    public static final String DATE_TIME = "yyyy-MM-dd[[ HH][:mm][:ss]]";
    public static final String DATE = "yyyy-MM-dd";
    public static final String DATE_MONTH = "yyyy-MM";
    public static final String DATE_YEAR = "yyyy";
    public static final String TIME_START = " 00:00:00";
    public static final String TIME_END = " 23:59:59";

    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();

    /**
     * LocalDateTime 转 字符串，指定日期格式
     *
     * @param localDateTime
     * @param pattern
     * @return
     */
    public static String format(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        String timeStr = formatter.format(localDateTime.atZone(DEFAULT_ZONE_ID));
        return timeStr;
    }

    /**
     * localDate 转 字符串，指定日期格式
     *
     * @param localDate
     * @return
     */
    public static String format(LocalDate localDate) {
        return localDate.format(DateTimeFormatter.ofPattern(DATE));
    }


    /**
     * localDate 转 字符串，指定日期格式
     *
     * @param localDateTime
     * @return
     */
    public static String formatDate(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern(DATE));
    }

    /**
     * 字符串 转 Date
     *
     * @param time
     * @return
     */
    public static LocalDateTime strToLocalDateTime(String time) {
        return strToLocalDateTime(time, defaultParseLocalDateTimeFormatter);
    }

    /**
     * 字符串 转 Date
     *
     * @param time
     * @return
     */
    public static LocalDateTime strToLocalDateTime(String time, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
        return localDateTime;
    }

    /**
     * 获取当月第一天
     *
     * @return
     */
    public static LocalDate getCurrentMonthFirstDay() {
        LocalDate date = LocalDate.now();
        LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); // 获取当前月的第一天
        return firstDay;
    }

    /**
     * 获取当月第一天
     *
     * @return
     */
    public static LocalDate getCurrentMonthLastDay() {
        LocalDate date = LocalDate.now();
        LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); // 获取当前月的最后一天
        return lastDay;
    }


    /**
     * 获取当年第一天
     *
     * @return
     */
    public static LocalDate getCurrentYearFirstDay() {
        LocalDate date = LocalDate.now();
        LocalDate lastDay = date.with(TemporalAdjusters.firstDayOfYear()); // 获取当前年的最后一天
        return lastDay;
    }

    /**
     * 获取之前的某一天
     *
     * @return
     */
    public static LocalDateTime getAnyBeforeDateTime(LocalDateTime datetime, long n) {
        return datetime.minusDays(n);
    }

    /**
     * 获取之前的某一天
     *
     * @return
     */
    public static LocalDate getAnyBeforeDate(LocalDate date, long n) {
        return date.minusDays(n);
    }

    public static LocalDateTime getEndTime(LocalDate date) {
        if (Objects.nonNull(date)) {
            return getLocalDateTime(format(date) + TIME_END);
        }
        return null;
    }

    public static LocalDateTime getStartTime(LocalDate date) {
        if (Objects.nonNull(date)) {
            return getLocalDateTime(format(date) + TIME_START);
        }
        return null;
    }

    private static LocalDateTime getLocalDateTime(String time) {
        if (StringUtils.isNotEmpty(time)) {
            return strToLocalDateTime(time, defaultParseLocalDateTimeFormatter);
        }
        return null;
    }

    public static LocalDateTime firstDayOfMonth(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 获取传入时间的n天以前的日期集合
     *
     * @param localDateTime
     * @param n
     * @param includeToday
     * @return
     */
    public static List<String> getTimesBefore(LocalDateTime localDateTime, int n, boolean includeToday) {
        List<String> times = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            times.add(formatDate(localDateTime.minusDays(n - i)));
        }
        if (includeToday) {
            times.add(formatDate(localDateTime));
        }
        return times;
    }

    /**
     * 获取传入时间的n天以前的日期集合
     *
     * @param includeToday
     * @param n
     * @return
     */
    public static List<String> getTimesBefore(int n, boolean includeToday) {
        return getTimesBefore(LocalDateTime.now(), n, includeToday);
    }

    /**
     * 获取传入时间的n天以前的日期集合
     *
     * @param n
     * @return
     */
    public static List<String> getTimesBefore(int n) {
        return getTimesBefore(LocalDateTime.now(), n, Boolean.TRUE);
    }

    public static Long getToTodayEndSecond() {
        // 获取当前时间的 LocalDateTime 对象
        LocalDateTime now = LocalDateTime.now();
        // 获取今日的截止时间（假设为当天的23:59:59）
        LocalDateTime endOfDay = now.with(LocalTime.of(23, 59, 59));
        // 计算毫秒数差值
        long millisecondsUntilEndOfDay = java.time.Duration.between(now, endOfDay).toMillis();
        return millisecondsUntilEndOfDay / 1000;
    }
}
